import requests
import re
import json
import time
from pyecharts.charts import Map
from pyecharts.charts import Bar
from pyecharts.charts import Line
from pyecharts import options as opts
from db.dbuntils import *
from db.dbconfig import *
import numpy as np
import wordcloud
from PIL import Image
import matplotlib.pyplot as plt
# 省和直辖市
province_distribution = {}
#数据统计
sumConfirm = 0
sumDead = 0
sumSuspected = 0
sumCured = 0


# 观察开发者工具network找到url
int_url = 'https://api.inews.qq.com/newsqa/v1/automation/foreign/country/ranklist'
# 找到显示国内疫情数据的url，如:
# 'https://panshi.qq.com/v2/vote/23311878?source=1&callback=jQuery35105457093859854443_1624342555735&_=1624342555736'
# 'jQuery35105457093859854443_1624342555735'可省略不写，其后面的数字为time.time()*1000，按照其格式构造url，即实时数据的url
cn_url = 'https://view.inews.qq.com/g2/getOnsInfo?name=disease_h5&callback=&_=%d' % int(time.time() * 1000)
usa_url = 'https://api.inews.qq.com/newsqa/v1/automation/foreign/daily/list?country=美国&='
china_url = 'https://api.inews.qq.com/newsqa/v1/query/inner/publish/modules/list?modules=chinaDayList,chinaDayAddList,nowConfirmStatis,provinceCompare'
worldmap_url = 'https://api.inews.qq.com/newsqa/v1/automation/foreign/country/ranklist'

def get_data_html():
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/14.0.835.163 Safari/535.1'}
    response = requests.get('https://ncov.dxy.cn/ncovh5/view/pneumonia?from=timeline&isappinstalled=0',
                            headers=headers, timeout=3)
    # 请求页面
    response = str(response.content, 'utf-8')
    # 中文重新编码
    return response
    # 返回了HTML数据


def get_data_dictype():
    areas_type_dic_raw = re.findall('try { window.getAreaStat = (.*?)}catch\(e\)', get_data_html())
    areas_type_dic = json.loads(areas_type_dic_raw[0])
    return areas_type_dic
    # 返回经过json转换过的字典化的数据

def startGrasp():
    result = get_data_dictype()
    db = pymysql.connect(host=db_address,
                         port=db_port,
                         user=db_username,
                         passwd=db_password,
                         db=db_name)
    sql = "truncate table t_china_covid_data"
    cur = db.cursor()
    cur.execute(sql)
    db.close()
    for item in result:
        print(item)
        provinceName = item['provinceName']
        provinceShortName = item['provinceShortName']
        currentConfirmedCount = item['currentConfirmedCount']
        confirmedCount = item['confirmedCount']
        suspectedCount = item['suspectedCount']
        curedCount = item['curedCount']
        deadCount = item['deadCount']
        comment = item['comment']
        locationId = item['locationId']
        global sumConfirm
        global sumDead
        global sumSuspected
        global sumCured
        sumConfirm = sumConfirm + confirmedCount
        sumSuspected = sumConfirm + suspectedCount
        sumCured = sumCured + curedCount
        sumDead = sumDead + deadCount
        province_distribution[provinceShortName] = province_distribution.get(provinceShortName,0) + confirmedCount
        sql = "insert into t_china_covid_data(provinceName,provinceShortName,currentConfirmedCount,confirmedCount,suspectedCount,curedCount,deadCount,comment,locaitionId) VALUES (%s,%s,%s,%s,%s,%s,%s,%s,%s)"
        params = (provinceName,provinceShortName,currentConfirmedCount,confirmedCount,suspectedCount,curedCount,deadCount,comment,locationId)
        db = pymysql.connect(host=db_address,
                             port=db_port,
                             user=db_username,
                             passwd=db_password,
                             db=db_name)

        # 使用cursor()方法获取操作游标
        cur = db.cursor()
        try:
            cur.execute(sql, params)
            db.commit()
        except Exception as e:
            print("错误信息：%s" % str(e))
            db.rollback()
        finally:
            db.close()
    print("爬取完毕！")


def get_int_page(page_int):    # 请求世界各国疫情数据
    try:
        response = requests.get(url=page_int)
        if response.status_code == 200:
            for item in response.json()['data']:
                print(item)
            print("爬取数据成功！")
            return response.json()['data']
    except requests.exceptions.ConnectionError as e:
        print('Error', e.args)



def parse_int_page(items_int):    # 解析世界各国疫情数据,并返回一个数据列表用于之后构造DataFrame
    data_int = []
    country_list = []
    country_confim_list = []
    country_dead_list = []
    country_heal_list = []

    for item_int in items_int:
        int_country = item_int.get('name')  # 国家
        int_confirm = item_int.get('confirm')  # 累计确诊人数
        int_dead = item_int.get('dead')  # 累计死亡人数
        int_heal = item_int.get('heal')  # 累计治愈人数
        int_nowConfirm = item_int.get('nowConfirm')  # 现有确诊人数
        int_confirm_add = item_int.get('confirmAdd')  # 新增确诊人数
        int_healCompare = item_int.get('healCompare')  # 新增治愈人数
        int_deadCompare = item_int.get('deadCompare')  # 新增死亡人数
        year = item_int.get('y')  # 当前年
        month, day = item_int.get('date').split('.')  # 当前月，日
        int_date = year + '-' + month + '-' + day
        country_list.append(int_country)
        country_confim_list.append(int_confirm)
        country_dead_list.append(int_heal)
        country_heal_list.append(int_heal)
        sql = "insert into t_foreign_covid_data(name,confirm,dead,heal,nowConfirm,confirmAdd,healCompare,deadCompare) VALUES (%s,%s,%s,%s,%s,%s,%s,%s)"
        params = (int_country,int_confirm,int_dead,int_heal,int_nowConfirm,int_confirm_add,int_healCompare,int_deadCompare)
        db = pymysql.connect(host=db_address,
                             port=db_port,
                             user=db_username,
                             passwd=db_password,
                             db=db_name)

        # 使用cursor()方法获取操作游标
        cur = db.cursor()
        try:
            cur.execute(sql, params)
            db.commit()
        except Exception as e:
            print("错误信息：%s" % str(e))
            db.rollback()
        finally:
            db.close()
    print("爬取完毕")
    return country_list,country_confim_list,country_dead_list,country_heal_list


def get_china_page(page_china):  # 请求中国每日疫情数据
    try:
        response = requests.get(url=page_china)
        if response.status_code == 200:
            return response.json()['data']
    except requests.exceptions.ConnectionError as e:
        print('Error', e.args)


def parse_china_page(items_china):    # 解析中国每日疫情数据
    china_list = []
    item_dayadds = items_china['chinaDayAddList']
    item_days = items_china['chinaDayList']
    for item_dayadd, item_day in zip(item_dayadds, item_days):
        year = item_dayadd['y']
        month, day = item_dayadd['date'].split('.')
        date = year + '-' + month + '-' + day
        china_confirm_add = item_dayadd['confirm']
        china_confirm = item_day['confirm']
        china_heal = item_day['heal']
        china_dead = item_day['dead']
        sql = "insert into t_chinaday_confim_data(date,china_confirm_add,china_confirm,china_heal,china_dead) VALUES (%s,%s,%s,%s,%s)"
        params = (date,china_confirm_add,china_confirm,china_heal,china_dead)
        db = pymysql.connect(host=db_address,
                             port=db_port,
                             user=db_username,
                             passwd=db_password,
                             db=db_name)

        # 使用cursor()方法获取操作游标
        cur = db.cursor()
        try:
            cur.execute(sql, params)
            db.commit()
        except Exception as e:
            print("错误信息：%s" % str(e))
            db.rollback()
        finally:
            db.close()
        china_dic = {'日期': date, '当日新增': china_confirm_add, '累计确诊': china_confirm,
                     '累计治愈': china_heal, '累计死亡': china_dead}
        china_list.append(china_dic)
    print("爬取完毕！")
    return china_list


def drawChinaLineChart():
    db = pymysql.connect(host=db_address,
                         port=db_port,
                         user=db_username,
                         passwd=db_password,
                         db=db_name)
    sql = "truncate table t_chinaday_confim_data"
    cur = db.cursor()
    cur.execute(sql)
    db.close()
    china_data = get_china_page(china_url)
    cn_list = parse_china_page(china_data)
    print(cn_list)
    dayList = []
    confirmList = []
    for item in cn_list:
        dayList.append(item['日期'])
        confirmList.append(item['当日新增'])
    (
        Line()
            .set_global_opts(
            title_opts=opts.TitleOpts(title="近两个月国内新冠疫情确诊人数折线图"),
            tooltip_opts=opts.TooltipOpts(is_show=False),
            xaxis_opts=opts.AxisOpts(type_="category"),
            yaxis_opts=opts.AxisOpts(
                type_="value",
                axistick_opts=opts.AxisTickOpts(is_show=True),
                splitline_opts=opts.SplitLineOpts(is_show=True),
            ),
        )
            .add_xaxis(xaxis_data=dayList)
            .add_yaxis(
            series_name="",
            y_axis=confirmList,
            symbol="emptyCircle",
            is_symbol_show=True,
            label_opts=opts.LabelOpts(is_show=False),
        )
            .render("新冠疫情折线图.html")
    )


def drawWorldBar():
    db = pymysql.connect(host=db_address,
                         port=db_port,
                         user=db_username,
                         passwd=db_password,
                         db=db_name)
    sql = "truncate table t_foreign_covid_data"
    cur = db.cursor()
    cur.execute(sql)
    db.close()
    int_data = get_int_page(int_url)
    list_data_int = parse_int_page(int_data)
    print(list_data_int[0])
    columns = list_data_int[0]
    data1 = list_data_int[1]
    data2 = list_data_int[2]
    data3 = list_data_int[3]
    bar = Bar()
    bar.add_xaxis(columns[:5])
    bar.add_yaxis("确诊人数",list_data_int[1][:5])
    bar.add_yaxis("治愈人数",list_data_int[3][:5])
    bar.set_global_opts(title_opts=opts.TitleOpts(title="新冠疫情感染前5名数据统计"))
    bar.render("世界疫情统计.html")
    print("生成成功!")


def makeWordCloud():
    # 请求数据
    url = "https://api.yimian.xyz/coro"
    data = requests.get(url).text
    json_data = json.loads(data)
    print(json_data)
    area_dict = dict()
    for province_name in json_data:
        if "cities" in province_name:
            # 判断国内
            for cities in province_name["cities"]:
                # print(cities)
                area = cities["cityName"]
                area_conf = int(cities["currentConfirmedCount"])
                area_dict[area] = area_conf
        else:
            # 判断国外
            area = province_name["provinceName"]
            area_conf = int(province_name["currentConfirmedCount"])
            area_dict[area] = area_conf

    # 生成词云
    heart_mask = np.array(Image.open("D:\\netbugwork\\map1.jpg"))
    wcloud = wordcloud.WordCloud(scale=32, background_color="white", mask=heart_mask, font_path='D:\\netbugwork\\msyh.ttc')
    wcloud.generate_from_frequencies(frequencies=area_dict)  # 根据数量的大小，越大的字体越大
    plt.figure(dpi=1000)
    plt.imshow(wcloud, interpolation='bilinear')
    plt.axis('off')
    # plt.show()
    plt.savefig("wuhan3.png")


def drawMap():
    startGrasp()
    try:
        map = Map()
        map.set_global_opts(
            title_opts=opts.TitleOpts(title="实时疫情地图\n\n累计确诊 %d\n现有疑似 %d\n累计治愈 %d\n累计死亡 %d" \
                                            % ( sumConfirm, \
                                               sumSuspected, sumCured,
                                               sumDead)),
            visualmap_opts=opts.VisualMapOpts(max_=3600, is_piecewise=True,
                                              pieces=[
                                                  {"max": 1999999, "min": 10000, "label": "10000人及以上",
                                                   "color": "#8A0808"},
                                                  {"max": 9999, "min": 1000, "label": "1000-9999人", "color": "#B40404"},
                                                  {"max": 999, "min": 500, "label": "500-999人", "color": "#DF0101"},
                                                  {"max": 499, "min": 100, "label": "100-499人", "color": "#F78181"},
                                                  {"max": 99, "min": 10, "label": "10-99人", "color": "#F5A9A9"},
                                                  {"max": 9, "min": 0, "label": "1-9人", "color": "#FFFFCC"},
                                              ], )  # 最大数据范围，分段
        )
        map.add("确诊", data_pair=list(province_distribution.items()), maptype="china", is_roam=True)
        map.render("实时疫情地图.html")
        print("生成成功!")
    except Exception as e:
        print("未爬取数据！")



def drawWorldMap():
    response = requests.post(worldmap_url).text
    resp = json.loads(response)  # 使用变量resp来接收字典格式的数据
    print(resp)
    map_version = {}  # 定义空字典
    for data in resp['data']:  # 遍历提取每个国家的疫情数据
        name = data['name']  # 国家名
        confirm = data['confirm']  # 该国家疫情人数
        map_version[name] = int(confirm)  # 将国家和人数以键值对的形式传入字典
    element = list(map_version.items())  # 将字典值调整为可以传入地图的格式
    name_map = {
        'Singapore Rep.': '新加坡',
        'Dominican Rep.': '多米尼加',
        'Palestine': '巴勒斯坦',
        'Bahamas': '巴哈马',
        'Timor-Leste': '东帝汶',
        'Afghanistan': '阿富汗',
        'Guinea-Bissau': '几内亚比绍',
        "Côte d'Ivoire": '科特迪瓦',
        'Siachen Glacier': '锡亚琴冰川',
        "Br. Indian Ocean Ter.": '英属印度洋领土',
        'Angola': '安哥拉',
        'Albania': '阿尔巴尼亚',
        'United Arab Emirates': '阿联酋',
        'Argentina': '阿根廷',
        'Armenia': '亚美尼亚',
        'French Southern and Antarctic Lands': '法属南半球和南极领地',
        'Australia': '澳大利亚',
        'Austria': '奥地利',
        'Azerbaijan': '阿塞拜疆',
        'Burundi': '布隆迪',
        'Belgium': '比利时',
        'Benin': '贝宁',
        'Burkina Faso': '布基纳法索',
        'Bangladesh': '孟加拉国',
        'Bulgaria': '保加利亚',
        'The Bahamas': '巴哈马',
        'Bosnia and Herz.': '波斯尼亚和黑塞哥维那',
        'Belarus': '白俄罗斯',
        'Belize': '伯利兹',
        'Bermuda': '百慕大',
        'Bolivia': '玻利维亚',
        'Brazil': '巴西',
        'Brunei': '文莱',
        'Bhutan': '不丹',
        'Botswana': '博茨瓦纳',
        'Central African Rep.': '中非',
        'Canada': '加拿大',
        'Switzerland': '瑞士',
        'Chile': '智利',
        'China': '中国',
        'Ivory Coast': '象牙海岸',
        'Cameroon': '喀麦隆',
        'Dem. Rep. Congo': '刚果民主共和国',
        'Congo': '刚果',
        'Colombia': '哥伦比亚',
        'Costa Rica': '哥斯达黎加',
        'Cuba': '古巴',
        'N. Cyprus': '北塞浦路斯',
        'Cyprus': '塞浦路斯',
        'Czech Rep.': '捷克',
        'Germany': '德国',
        'Djibouti': '吉布提',
        'Denmark': '丹麦',
        'Algeria': '阿尔及利亚',
        'Ecuador': '厄瓜多尔',
        'Egypt': '埃及',
        'Eritrea': '厄立特里亚',
        'Spain': '西班牙',
        'Estonia': '爱沙尼亚',
        'Ethiopia': '埃塞俄比亚',
        'Finland': '芬兰',
        'Fiji': '斐',
        'Falkland Islands': '福克兰群岛',
        'France': '法国',
        'Gabon': '加蓬',
        'United Kingdom': '英国',
        'Georgia': '格鲁吉亚',
        'Ghana': '加纳',
        'Guinea': '几内亚',
        'Gambia': '冈比亚',
        'Guinea Bissau': '几内亚比绍',
        'Eq. Guinea': '赤道几内亚',
        'Greece': '希腊',
        'Greenland': '格陵兰',
        'Guatemala': '危地马拉',
        'French Guiana': '法属圭亚那',
        'Guyana': '圭亚那',
        'Honduras': '洪都拉斯',
        'Croatia': '克罗地亚',
        'Haiti': '海地',
        'Hungary': '匈牙利',
        'Indonesia': '印度尼西亚',
        'India': '印度',
        'Ireland': '爱尔兰',
        'Iran': '伊朗',
        'Iraq': '伊拉克',
        'Iceland': '冰岛',
        'Israel': '以色列',
        'Italy': '意大利',
        'Jamaica': '牙买加',
        'Jordan': '约旦',
        'Japan': '日本',
        'Kazakhstan': '哈萨克斯坦',
        'Kenya': '肯尼亚',
        'Kyrgyzstan': '吉尔吉斯斯坦',
        'Cambodia': '柬埔寨',
        'Korea': '韩国',
        'Kosovo': '科索沃',
        'Kuwait': '科威特',
        'Lao PDR': '老挝',
        'Lebanon': '黎巴嫩',
        'Liberia': '利比里亚',
        'Libya': '利比亚',
        'Sri Lanka': '斯里兰卡',
        'Lesotho': '莱索托',
        'Lithuania': '立陶宛',
        'Luxembourg': '卢森堡',
        'Latvia': '拉脱维亚',
        'Morocco': '摩洛哥',
        'Moldova': '摩尔多瓦',
        'Madagascar': '马达加斯加',
        'Mexico': '墨西哥',
        'Macedonia': '马其顿',
        'Mali': '马里',
        'Myanmar': '缅甸',
        'Montenegro': '黑山',
        'Mongolia': '蒙古',
        'Mozambique': '莫桑比克',
        'Mauritania': '毛里塔尼亚',
        'Malawi': '马拉维',
        'Malaysia': '马来西亚',
        'Namibia': '纳米比亚',
        'New Caledonia': '新喀里多尼亚',
        'Niger': '尼日尔',
        'Nigeria': '尼日利亚',
        'Nicaragua': '尼加拉瓜',
        'Netherlands': '荷兰',
        'Norway': '挪威',
        'Nepal': '尼泊尔',
        'New Zealand': '新西兰',
        'Oman': '阿曼',
        'Pakistan': '巴基斯坦',
        'Panama': '巴拿马',
        'Peru': '秘鲁',
        'Philippines': '菲律宾',
        'Papua New Guinea': '巴布亚新几内亚',
        'Poland': '波兰',
        'Puerto Rico': '波多黎各',
        'Dem. Rep. Korea': '朝鲜',
        'Portugal': '葡萄牙',
        'Paraguay': '巴拉圭',
        'Qatar': '卡塔尔',
        'Romania': '罗马尼亚',
        'Russia': '俄罗斯',
        'Rwanda': '卢旺达',
        'W. Sahara': '西撒哈拉',
        'Saudi Arabia': '沙特阿拉伯',
        'Sudan': '苏丹',
        'S. Sudan': '南苏丹',
        'Senegal': '塞内加尔',
        'Solomon Is.': '所罗门群岛',
        'Sierra Leone': '塞拉利昂',
        'El Salvador': '萨尔瓦多',
        'Somaliland': '索马里兰',
        'Somalia': '索马里',
        'Serbia': '塞尔维亚',
        'Suriname': '苏里南',
        'Slovakia': '斯洛伐克',
        'Slovenia': '斯洛文尼亚',
        'Sweden': '瑞典',
        'Swaziland': '斯威士兰',
        'Syria': '叙利亚',
        'Chad': '乍得',
        'Togo': '多哥',
        'Thailand': '泰国',
        'Tajikistan': '塔吉克斯坦',
        'Turkmenistan': '土库曼斯坦',
        'East Timor': '东帝汶',
        'Trinidad and Tobago': '特里尼达和多巴哥',
        'Tunisia': '突尼斯',
        'Turkey': '土耳其',
        'Tanzania': '坦桑尼亚',
        'Uganda': '乌干达',
        'Ukraine': '乌克兰',
        'Uruguay': '乌拉圭',
        'United States': '美国',
        'Uzbekistan': '乌兹别克斯坦',
        'Venezuela': '委内瑞拉',
        'Vietnam': '越南',
        'Vanuatu': '瓦努阿图',
        'West Bank': '西岸',
        'Yemen': '也门',
        'South Africa': '南非',
        'Zambia': '赞比亚',
        'Zimbabwe': '津巴布韦',
        'Comoros': '科摩罗'
    }

    map = Map(opts.InitOpts(bg_color="#87CEFA", page_title='世界疫情分布')). \
        add(series_name="世界疫情分布图",  # 名称
            data_pair=element,  # 传入数据
            is_map_symbol_show=False,  # 不显示标记
            maptype='world',  # 地图类型
            name_map=name_map,
            )
    # 设置全局配置项
    map.set_global_opts(visualmap_opts=opts.VisualMapOpts(max_=1100000, is_piecewise=True, pieces=[
        {"min": 500000},
        {"min": 200000, "max": 499999},
        {"min": 100000, "max": 199999},
        {"min": 50000, "max": 99999},
        {"min": 10000, "max": 49999},
        {"max": 9999}, ]))
    # 设置系列配置项
    map.set_series_opts(label_opts=opts.LabelOpts(is_show=False))  # 不显示国家名
    print("生成成功！")
    map.render('世界疫情地图.html')  # 命名并保存

